package com.hexinfo.dmpro.monitor.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.hexinfo.dmpro.common.base.BaseService;
import com.hexinfo.dmpro.common.base.Page;
import com.hexinfo.dmpro.common.base.PageResult;
import com.hexinfo.dmpro.common.utils.StringUtils;
import com.hexinfo.dmpro.monitor.config.MonitorConfig;
import com.hexinfo.dmpro.monitor.dao.ClusterWhDao;
import com.hexinfo.dmpro.monitor.dao.ImpalaAppDao;
import com.hexinfo.dmpro.monitor.dao.MonitorDao;
import com.hexinfo.dmpro.monitor.dao.YarnAppDao;
import com.hexinfo.dmpro.monitor.model.ImpalaAppModel;
import com.hexinfo.dmpro.monitor.model.MonitorClusResModel;
import com.hexinfo.dmpro.monitor.model.MonitorTaskModel;
import com.hexinfo.dmpro.monitor.model.YarnAppModel;
import com.hexinfo.dmpro.monitor.model.base.MonitorReq;
import com.hexinfo.dmpro.monitor.util.ConnMysqlUtil;
import com.hexinfo.dmpro.monitor.util.ConvertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @author peng
 * @date 2021/10/13 19:39
 */
@Slf4j
@Service
public class MonitorService extends BaseService {

    @Autowired
    private YarnAppDao yarnAppDao;
    @Autowired
    private ImpalaAppDao impalaAppDao;
    @Autowired
    private MonitorConfig monitorConfig;
    @Autowired
    private MonitorDao monitorDao;
    @Autowired
    private ConvertUtil convertUtil;
    @Autowired
    private ClusterWhDao clusterWhDao;
    @Autowired
    private CmStateService cmStateService;

    private static String YARN_TYPE = "YARN";
    private static String IMPALA_TYPE = "IMPALA";

    /**
     * 查询配置数据
     *
     * @return
     */
    public Map<String, Object> selAllCluster(MonitorClusResModel req) {
        Map<String, Object> rspMap = new HashMap<>();
        Map<String, String> reqMap = new HashMap<>();
        reqMap.put("centerId", monitorConfig.getNowCenterId());
        reqMap.put("cmFlag", req.getCmFlag());
        reqMap.put("clusterFlag", req.getClusterFlag());
        List<Map<String, String>> clusterList = monitorDao.selAllCluster(reqMap);
        List<Map<String, String>> queueList = monitorDao.selAllQueue(reqMap);
        List<Map<String, String>> unitList = monitorDao.selAllUnit(reqMap);
        List<Map<String, String>> userList = monitorDao.selAllUser(reqMap);
        rspMap.put("clusterOptions", clusterList);
        rspMap.put("queueOptions", queueList);
        rspMap.put("userOptions", userList);
        rspMap.put("unitOptions", unitList);
        return rspMap;
    }


    /**
     * 作业数量统计图表
     *
     * @param req
     * @return
     */
    public List selTaskJobCount(MonitorReq req) {
        if (req.getDateTimeData() != null && req.getDateTimeData().length > 0) {
            req.setStartTime(req.getDateTimeData()[0]);
            req.setEndTime(req.getDateTimeData()[1]);
        } else {
            req.setStartTime(LocalDate.now().toString());
        }
        List<Map<String, Object>> maps = null;
        if (req.getMonitorType().equals("YARN")) {
//            if (req.getStartTime().substring(0, 10).equals(LocalDate.now().toString())) {
//                maps = monitorDao.selTaskJobYarnCountNow(req);
//            } else {
                maps = monitorDao.selTaskJobYarnCount(req);
//            }

        } else {
//            if (req.getStartTime().substring(0, 10).equals(LocalDate.now().toString())) {
//                maps = monitorDao.selTaskJobImaplaCountNow(req);
//            } else {
                maps = monitorDao.selTaskJobImaplaCount(req);
//            }
        }
        return maps;
    }

    /**
     * 作业执行时间统计图表
     *
     * @param req
     * @return
     */
    public List selTaskJobTime(MonitorReq req) {
        if (req.getDateTimeData() != null && req.getDateTimeData().length > 0) {
            req.setStartTime(req.getDateTimeData()[0]);
            req.setEndTime(req.getDateTimeData()[1]);
        } else {
            req.setStartTime(LocalDate.now().toString());
        }
        List<Map<String, Object>> maps = null;
        if (req.getMonitorType().equals("YARN")) {
//            if (req.getStartTime().substring(0, 10).equals(LocalDate.now().toString())) {
//                maps = monitorDao.selTaskJobYarnTimeNow(req);
//            } else {
                maps = monitorDao.selTaskJobYarnTime(req);
//            }
        } else {
//            if (req.getStartTime().substring(0, 10).equals(LocalDate.now().toString())) {
//                maps = monitorDao.selTaskJobImpalaTimeNow(req);
//            } else {
                maps = monitorDao.selTaskJobImpalaTime(req);
//            }
        }
        return maps;
    }

    /**
     * 查询任务信息
     *
     * @param req
     * @return
     */
    public PageResult selTaskInfo(Page page, MonitorReq req) {
        String[] dataDate = req.getDataDate();
        //如果日期参数为空默认查询当天的数据
        if (dataDate != null && dataDate.length > 0) {
            req.setStartTime(dataDate[0]);
            req.setEndTime(dataDate[1]);
        } else {
            req.setStartTime(LocalDate.now().toString());
        }
        MonitorTaskModel monitorTaskModel = new MonitorTaskModel();
        //获取具体任务信息
        PageResult pageResult = null;
        String monitorType = req.getMonitorType();
        if (YARN_TYPE.equals(monitorType)) {
            //如果开始时间是当天 则查询 now 表
//            if (req.getStartTime().substring(0, 10).equals(LocalDate.now().toString())) {
//                pageResult = selectPage(yarnAppDao, "selectYarnAppNow", page, req);
//            } else {
                pageResult = selectPage(yarnAppDao, "selectYarnApp", page, req);
//            }
            //前端数值展示，灵活调整单位
            if (pageResult != null) {
                List<YarnAppModel> yarnAppModels = (List<YarnAppModel>)pageResult.getContent();
                for (YarnAppModel yarnAppModel : yarnAppModels) {
                    yarnAppModel.setApplicationDuration(deaLMs(yarnAppModel.getElapsedTime()));
                    yarnAppModel.setMbMillis(getPrintSize(yarnAppModel.getMbMillis()));
                    yarnAppModel.setVcoresMillis(getPrintSizeK(yarnAppModel.getVcoresMillis()));
                    yarnAppModel.setHdfsBytesRead(getPrintSize(yarnAppModel.getHdfsBytesRead()));
                    yarnAppModel.setHdfsBytesWritten(getPrintSize(yarnAppModel.getHdfsBytesWritten()));
                    yarnAppModel.setFileBytesRead(getPrintSize(yarnAppModel.getFileBytesRead()));
                    yarnAppModel.setFileBytesWritten(getPrintSize(yarnAppModel.getFileBytesWritten()));
                    yarnAppModel.setMemorySeconds(numRounding(yarnAppModel.getMemorySeconds()));
                    yarnAppModel.setVcoreSeconds(numRounding(yarnAppModel.getVcoreSeconds()));
                    yarnAppModel.setAllocatedMBStr(numRounding(Long.toString(yarnAppModel.getAllocatedMB())));
                }
            }
        } else if (IMPALA_TYPE.equals(monitorType)) {
            //如果开始时间是当天 则查询 now 表
//            if (req.getStartTime().substring(0, 10).equals(LocalDate.now().toString())) {
//                pageResult = selectPage(impalaAppDao, "selectImpalaAppNow", page, req);
//            } else {
                pageResult = selectPage(impalaAppDao, "selectImpalaApp", page, req);
//            }
            //前端数值展示，灵活调整单位
            if (pageResult != null) {
                List<ImpalaAppModel> impalaAppModels = (List<ImpalaAppModel>)pageResult.getContent();
                for (ImpalaAppModel impalaAppModel : impalaAppModels) {
                    impalaAppModel.setDuration(deaLMs(impalaAppModel.getDuration()));
                }
            }
        }
        return pageResult;
    }

    public String numRounding(String req) {
        DecimalFormat df = new DecimalFormat("#.#");
        double du = Double.parseDouble(req);
        //K
        int compare = Double.compare(du, 1000.0);
        if (compare > 0){
            du = du/1000;
        }else {
            return Math.round(du)+"";
        }
        //M
        int compare1 = Double.compare(du, 1000.0);
        if (compare1 > 0){
            du = du/1000;
        }else {
            return df.format(du)+"K";
        }
        //G
        int compare2 = Double.compare(du, 1000.0);
        if (compare2 > 0){
            du = du/1000;
        }else {
            return Math.round(du)+"M";
        }
        return df.format(du)+"G";
    }

    /**
     * 查询任务数量
     *
     * @param req
     * @return
     */
    public MonitorTaskModel selTaskCount(MonitorReq req) {
        MonitorTaskModel monitorTaskModel = new MonitorTaskModel();
        //获取任务数量
        Map<String, Object> map = monitorDao.selTaskCount(req);
        if (map != null) {
            monitorTaskModel.setToDaySubmit(Integer.parseInt(map.get("toDaySubmit").toString()));
            monitorTaskModel.setToDayRunning(Integer.parseInt(map.get("toDayRunning").toString()));
            monitorTaskModel.setToDaySucceeded(Integer.parseInt(map.get("toDaySucceeded").toString()));
            monitorTaskModel.setToDayFailed(Integer.parseInt(map.get("toDayFailed").toString()));
        } else {
            monitorTaskModel.setToDaySubmit(0);
            monitorTaskModel.setToDayRunning(0);
            monitorTaskModel.setToDaySucceeded(0);
            monitorTaskModel.setToDayFailed(0);
        }
        return monitorTaskModel;
    }

    /**
     * 毫秒展示单位换算
     *
     * @param time
     * @return
     */
    public static String deaLMs(String time) {
        if(StringUtils.isBlank(time)){
            return null;
        }
        long ms = Long.parseLong(time.replace(".0", ""));
        Integer ss = 1000;
        Integer mi = ss * 60;
        Integer hh = mi * 60;
        Integer dd = hh * 24;
        Long day = ms / dd;
        Long hour = (ms - day * dd) / hh;
        Long minute = (ms - day * dd - hour * hh) / mi;
        Long second = (ms - day * dd - hour * hh - minute * mi) / ss;
        Long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss;
        StringBuffer sb = new StringBuffer();
        if (day > 0) {
            sb.append(day + "d");
        }
        if (hour > 0) {
            sb.append(hour + "h");
        }
        if (minute > 0) {
            sb.append(minute + "m");
        }
        if (second > 0) {
            sb.append(second + "s");
        }
        if (time.length() < 4 && milliSecond > 0) {
            sb.append(milliSecond + "ms");
        }
        return sb.toString();
    }

    public static String getPrintSize(String l) {
        if(StringUtils.isBlank(l)){
            return null;
        }
        long size = Long.parseLong(l);
        //如果字节数少于1024，则直接以B为单位，否则先除于1024，后3位因太少无意义
        if (size < 1024) {
            return String.valueOf(size) + "B";
        } else {
            size = size / 1024;
        }
        //如果原字节数除于1024之后，少于1024，则可以直接以KB作为单位
        //因为还没有到达要使用另一个单位的时候
        //接下去以此类推
        if (size < 1024) {
            return String.valueOf(size) + "KB";
        } else {
            size = size / 1024;
        }
        if (size < 1024) {
            //因为如果以MB为单位的话，要保留最后1位小数，
            //因此，把此数乘以100之后再取余
            size = size * 100;
            return String.valueOf((size / 100)) + "."
                    + String.valueOf((size % 100)) + "MB";
        } else {
            //否则如果要以GB为单位的，先除于1024再作同样的处理
            size = size * 100 / 1024;
            return String.valueOf((size / 100)) + "."
                    + String.valueOf((size % 100)) + "GB";
        }
    }

    public static String getPrintSizeK(String l) {
        if(StringUtils.isBlank(l)){
            return null;
        }
        long size = Long.parseLong(l);
        double result = (double) size / 1000;
        return String.valueOf(String.format("%.1f", result)) + 'K';
    }

    /**
     * 任务状态数量汇总
     * @return
     */
    public MonitorTaskModel selTaskStateCount(String areaId,String sortId,String monitorType) {
        MonitorReq monitorReq = clusterWhDao.queryAreaIdSortId(areaId,sortId);
        monitorReq.setMonitorType(monitorType);
        return selTaskCount(monitorReq);
    }

    /**
     * 作业数量时间统计图表
     * @return
     */
    public List selTaskJobCountTime(String areaId,String sortId) {
        MonitorReq req = clusterWhDao.queryAreaIdSortId(areaId,sortId);
        return monitorDao.selTaskJobCountTime(req);
    }

    /**
     * 服务状态
     * @return
     */
    public List selServiceState(String areaId,String sortId) {
        MonitorReq req = clusterWhDao.queryAreaIdSortId(areaId,sortId);
        return cmStateService.selServiceState(req);
    }

}
